package com.cirkana.viewer.map;

import java.io.DataInputStream;
import java.io.DataOutputStream;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.location.Location;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.WebView;
import android.widget.Button;

import com.cirkana.PassData;
import com.cirkana.ViewerActivity;
import com.cirkana.serial.bin.BinarySerializationException;
import com.cirkana.serial.bin.BinarySerializationUtil;
import com.cirkana.viewer.R;
import com.cirkana.viewer.data.route.RouteDetail;
import com.cirkana.viewer.data.security.User;
import com.cirkana.viewer.map.location.MapLocationManager;
import com.cirkana.viewer.share.IShareServiceProxy;
import com.cirkana.viewer.share.ShareActivity;
import com.cirkana.viewer.share.ShareActivity.SharePassData;

public class MapActivity extends ViewerActivity {

	public static final int REQUEST_SHARE = 1;

	private WebView mapWebView;

	private MapPassData data;
	private MapCommunicator communicator;
	private MapLocationManager locationManager;

	private String[] locationProviders;
	private Integer currentLocationProvider;
	private Location currentLocation;
	private User currentUser;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.map);

		this.mapWebView = (WebView) findViewById(R.id.map_map);

		this.data = (MapPassData) this.getRequest(MapPassData.class);
		this.currentUser = this.data.getUser();
		this.communicator = new MapCommunicator();
		this.locationManager = new MapLocationManager(this, this.communicator);
		this.locationProviders = this.locationManager.getLocationProviders();

		// try {
		// this.communicator.addTrackerMessages(DataResolverUtil.getRouteDataResolver().getRemoteGpxRoute(this.data.getRouteDetail().getId()));
		// } catch (DataException e) {
		// showErrorMessage(e);
		// }

		this.currentLocationProvider = getLocationProvider();
		setLocationProvider(this.currentLocationProvider);

		this.mapWebView.getSettings().setJavaScriptEnabled(true);
		this.mapWebView.loadUrl("file:///android_asset/mapviewer.html");
		this.mapWebView.addJavascriptInterface(communicator, "comm");
	}

	private Integer getLocationProvider() {
		if (this.locationProviders.length > 0)
			return 0;
		else
			return null;
	}

	private void setLocationProvider(Integer locationProvider) {
		if (locationProvider != null) {
			this.locationManager.start(this.locationProviders[locationProvider]);
			this.currentLocation = this.locationManager.getLastKnownLocation(this.locationProviders[locationProvider]);
			if (this.currentLocation != null)
				this.communicator.addChangeLocationMessage(this.currentLocation);
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.map_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {

		case R.id.menu_map_change_location_provider:
			changeLocationProvider();
			return true;

		case R.id.menu_map_change_location:
			changeLocation();
			return true;

		case R.id.menu_map_share_twitter:
			try {
				startActivityForResult(ShareActivity.class, REQUEST_SHARE, new SharePassData(IShareServiceProxy.SHARE_SERVICE_TWITTER, this.currentUser));
			} catch (BinarySerializationException e) {
				showErrorMessage(e);
			}
			return true;

			// case R.id.menu_map_catch_picture:
			// return true;
			//
			// case R.id.menu_map_catch_qr:
			// startActivity(new Intent(this, QRReaderActivity.class));
			// return true;
			//
			// case R.id.menu_map_show_ar:
			// startActivity(new Intent(this, ARActivity.class));
			// return true;

		default:
			return super.onOptionsItemSelected(item);
		}
	}

	protected void changeLocationProvider() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getLiteral(R.string.change_provider));
		builder.setSingleChoiceItems(this.locationProviders, this.currentLocationProvider, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int item) {
				setLocationProvider(item);
				dialog.dismiss();
			}
		});
		AlertDialog alert = builder.create();
		alert.show();
	}

	protected void changeLocation() {
		final Dialog dialog = new Dialog(this);
		dialog.setContentView(R.layout.selectlocation);
		dialog.setTitle(getLiteral(R.string.change_location));
		dialog.getWindow().setLayout(getWindowManager().getDefaultDisplay().getWidth() - 15, getWindowManager().getDefaultDisplay().getHeight() - 30);

		final SelectLocationCommunicator comm = new SelectLocationCommunicator();
		if (this.currentLocation != null)
			comm.setLocation(this.currentLocation.getLatitude(), this.currentLocation.getLongitude());
		else
			comm.setLocation(41.38795, 2.176838);

		WebView locatorWebView = (WebView) dialog.findViewById(R.id.select_location_map);
		locatorWebView.getSettings().setJavaScriptEnabled(true);
		locatorWebView.loadUrl("file:///android_asset/maplocator.html");
		locatorWebView.addJavascriptInterface(comm, "comm");

		Button changeLocationButton = (Button) dialog.findViewById(R.id.select_location_change_location);
		changeLocationButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				if (currentLocation == null)
					currentLocation = new Location(locationProviders[currentLocationProvider]);
				currentLocation.setLatitude(comm.getLatitudeValue());
				currentLocation.setLongitude(comm.getLongitudeValue());
				communicator.addChangeLocationMessage(currentLocation);
				dialog.dismiss();
			}
		});

		dialog.show();
	}

	// @Override
	// protected void onActivityResult(int requestCode, int resultCode, Intent
	// data) {
	// super.onActivityResult(requestCode, resultCode, data);
	//
	// switch (requestCode) {
	// case RESULT_CANCELED:
	// break;
	// }
	// break;
	//
	// case RESULT_CANCELED:
	// break;
	// }
	// break;
	//
	// case REQUEST_SHARE:
	// switch (resultCode) {
	// case RESULT_OK:
	// break;
	// case RESULT_CANCELED:
	// break;
	// }
	// }
	//
	// }

	public static class MapPassData extends PassData {

		private RouteDetail routeDetail;
		private User user;

		public RouteDetail getRouteDetail() {
			return routeDetail;
		}

		public void setRouteDetail(RouteDetail routeDetail) {
			this.routeDetail = routeDetail;
		}

		public User getUser() {
			return this.user;
		}

		public void setUser(User user) {
			this.user = user;
		}

		public MapPassData() {
		}

		public MapPassData(RouteDetail routeDetail, User user) {
			this.routeDetail = routeDetail;
			this.user = user;
		}

		@Override
		public void serialize(DataOutputStream out) throws BinarySerializationException {
			BinarySerializationUtil.serializeSerializable(this.user, out);
			BinarySerializationUtil.serializeSerializable(this.routeDetail, out);
		}

		@Override
		public void deserialize(DataInputStream in) throws BinarySerializationException {
			this.user = (User) BinarySerializationUtil.deserializeSerializable(User.class, in);
			this.routeDetail = (RouteDetail) BinarySerializationUtil.deserializeSerializable(RouteDetail.class, in);
		}

		@Override
		public String toString() {
			StringBuilder s = new StringBuilder("{");

			s.append("tracker=");
			if (this.routeDetail == null)
				s.append("(null)");
			else
				s.append(this.routeDetail.toString());
			s.append("}");

			return s.toString();
		}
	}

	private class SelectLocationCommunicator {
		private double latitude;
		private double longitude;

		protected SelectLocationCommunicator() {
		}

		@SuppressWarnings("unused")
		public String getLatitude() {
			return Double.toString(latitude);
		}

		@SuppressWarnings("unused")
		public void setLatitude(String latitude) {
			this.latitude = Double.parseDouble(latitude);
		}

		@SuppressWarnings("unused")
		public String getLongitude() {
			return Double.toString(longitude);
		}

		@SuppressWarnings("unused")
		public void setLongitude(String longitude) {
			this.longitude = Double.parseDouble(longitude);
		}

		protected void setLocation(Double latitude, Double longitude) {
			this.latitude = latitude;
			this.longitude = longitude;
		}

		protected Double getLatitudeValue() {
			return this.latitude;
		}

		protected Double getLongitudeValue() {
			return this.longitude;
		}
	}

}